環境変数地獄にはAWS Secrets Managerで立ち向かえ! 〜ECS開発・運用のつらみ〜 您所在的位置:网站首页 aws secrets manager 環境変数地獄にはAWS Secrets Managerで立ち向かえ! 〜ECS開発・運用のつらみ〜

環境変数地獄にはAWS Secrets Managerで立ち向かえ! 〜ECS開発・運用のつらみ〜

2023-03-11 13:23| 来源: 网络整理| 查看: 265

はじめに

Twelve Factor App に準拠する Amazon ECS でのアプリケーション開発・運用の悩みの種の一つに「環境変数地獄」[1]があります。

環境ごと、サービスごとに倍々に膨れ上がる環境変数をどう管理するべきかという問題です。

AWS Secrets Manager を使うと AWS でアプリケーションと環境変数を安全に分離して管理することができます。

AWS Secrets Manager を活用することで Amazon ECS における環境変数の管理をなるべく簡潔にしようというのがこの記事の主旨です。

Twelve Factor App ってなに?

Twelve Factor App とは、Heroku のエンジニア集団による SaaS を作り上げるためのベストプラクティスです。 Twelve Factor App は名前の通り、下記の 12 個の項目でまとめられています。

I. コードベース バージョン管理されている 1 つのコードベースと複数のデプロイ II. 依存関係 依存関係を明示的に宣言し分離する III. 設定 設定を環境変数に格納する IV. バックエンドサービス バックエンドサービスをアタッチされたリソースとして扱う V. ビルド、リリース、実行 ビルド、リリース、実行の 3 つのステージを厳密に分離する VI. プロセス アプリケーションを 1 つもしくは複数のステートレスなプロセスとして実行する VII. ポートバインディング ポートバインディングを通してサービスを公開する VIII. 並行性 プロセスモデルによってスケールアウトする IX. 廃棄容易性 高速な起動とグレースフルシャットダウンで堅牢性を最大化する X. 開発/本番一致 開発、ステージング、本番環境をできるだけ一致させた状態を保つ XI. ログ ログをイベントストリームとして扱う XII. 管理プロセス 管理タスクを 1 回限りのプロセスとして実行する

この Twelve Factor App の項目の中でも、今回取り上げているのは「III. 設定」です。

設定の項目には、設定とコードを分離し、設定は環境変数として格納するということが述べられています。

アプリケーションは時に設定を定数としてコード内に格納する。これは Twelve-Factor に違反している。Twelve-Factor は 設定をコードから厳密に分離すること を要求する。

Twelve-Factor App は設定を 環境変数 に格納する。

具体的には、開発・検証・本番といった環境ごとに異なるデータベースの認証情報や AWS のシークレットキーなどの変数は config ファイルにハードコードするのではなく、環境変数として管理しようというものです。

なぜなら、config ファイルでの設定情報管理はうまくスケールしないためです。 アプリケーションのデプロイが増えるにつれて、新しい環境の config ファイルが必要になります。

さらに、プロジェクトが拡大すると、開発者は yoshimura-staging のような自分用の環境を追加することになり、結果として設定が組み合わせ的に爆発し、アプリケーションのデプロイの管理が非常に不安定になるということが述べられています。

詳細はIII. 設定のページを参照してください。

Twelve Factor App のこのベストプラクティスに従い Amazon ECS でアプリケーション開発・運用をした結果待ち受けているのが、 環境変数地獄 です。

環境ごとに倍々に膨れ上がった環境変数をどう管理するのかという課題です。 この課題に AWS Secrets Manager で立ち向かいます。

AWS Secrets Manager の紹介の前に Amazon ECS について軽く触れておきたいと思います。

Amazon Elastic Container Service(Amazon ECS) ってなに?

Amazon Elastic Container Service (Amazon ECS) は、 AWS 独自のコンテナオーケストレーションサービスです。Docker コンテナ化されたアプリケーションを AWS で簡単に実行・停止およびスケールを行うことができます。

Amazon ECS は従来まで EC2 インスタンスしか選択できませんでしたが、2018 年 7 月に東京リージョンでサービススタートとなった AWS Fargate を利用することで、EC2 インスタンスの管理が不要になります。これにより、EC2 のスケールを意識せずともコンテナのオートスケールが可能になるなどのメリットを享受することができます。

Amazon ECS や Fargate に関しては大変参考になる記事がありますので紹介させていただきます。

ECS 運用のノウハウ AmazonECS / Fargate 本番運用のための構築とデプロイ方法まとめ AWS Fargate とは?

Amazon ECS は調べた限りだと、S3 での環境変数管理を推奨しているようです。

設定情報を Amazon S3 のプライベートバケットに保存し、コンテナインスタンスの IAM ロールに読み取り専用アクセス権限を付与するのが、コンテナインスタンスの起動時に設定を許可する安全で便利な方法です

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/ecs-agent-config.html

しかし、S3 はマネージドコンソールで編集できないのがかなりつらく、環境変数を更新する際、ファイルをダウンロードして編集してアップロードして・・・のような職人の手作業が発生してしまいます。

これを回避するために AWS Secrets Manager を選択しています。 CLI の 1 コマンドでダウンロード・編集・アップロードを行ってくれる便利ツール [2] も確認できましたが、AWS のマネージドなサービスに乗っかるのがいいのではないかという判断です。(自作ツールはメンテナンスされ続けるか不安...)

それでは、今回の主役、AWS Secrets Manager の紹介です。

AWS Secrets Manager ってなに?

AWS Secrets Manager とは、データベースの認証情報や APIKey などのアプリケーションの環境変数を安全に格納・配布・交換・使用できるシークレット管理サービスです。

Amazon RDS for MySQL、PostgreSQL、Amazon Aurora への統合を組み込むことで DB の認証情報のローテーションが提供されるのが パラメータストア との違いの一つです。

今回、Amazon ECS でのアプリケーション開発・運用における環境変数管理ツールとして AWS Secrets Manager を利用します。

※ AWS Secrets Manager のチュートリアルがあります。環境が整っていれば数十分でできてしまうのでぜひ試してみてください。実際に触ってみることが一番理解が進みます。 https://docs.aws.amazon.com/ja_jp/secretsmanager/latest/userguide/tutorials_basic.html

AWS Secrets Manager へのアクセス方法

早速、AWS Secrets Manager に環境変数を登録・取得してみましょう。アクセス方法は大きく 3 つあります。

1. AWS マネジメントコンソール

image

AWS マネジメントコンソールでは、GUI で環境変数の登録・取得・編集・削除が行えます。

環境変数の微修正などにはとても便利ですが、複数の環境変数を追加する場合は一つ一つ追加する必要があるので、とても手間がかかりますしミスをしてしまう可能性もあります。

また、AWS Secrets Manager の仕様なのか、A-Z で環境変数をソートしてくれず、追加順でしか表示できません。(ここは今後アップデートで改修されるかもしれません。)

環境変数の微修正などの目的以外は、CLI からの登録がおすすめです。

メリット

GUI で操作できる 環境変数の微修正は便利

デメリット

一度に複数の環境変数を追加したい場合は不便 環境変数を A-Z でソートしてくれない 2. AWS CLI

https://docs.aws.amazon.com/cli/latest/reference/secretsmanager/index.html

AWS CLI が利用できるように準備をしてください。利用方法は適宜調べてください。 IAM やリージョンを適切に設定してから以下のコマンドで AWS Secrets Manager に環境変数の登録ができます。

aws secretsmanager create-secret --name xxx --description xxxx --secret-string file://example.json

create-secret オプションは新規作成時のみ有効なので、環境変数を更新する場合は put-secret-value オプションを利用する必要があります。同様に削除のオプションもあります。

example.json は シークレットのプレーンテキストで表示されるフォーマットです。(ドキュメントで提示されているフォーマットだとうまくいかなかったので注意が必要です。)

{ "Key" : "Value", "USER_NAME" : "user_name", "PASSWORD": "password" ... }

このフォーマットの json 形式で管理しておくと環境変数の作成や更新が CLI から行えるので便利です。

例えば新たに環境を増やす場合、ベースとなる環境の json ファイルをコピーして値を適切な値に書き換えるだけで、その json ファイルを元に新しい環境の環境変数を AWS Secrets Manager に登録することができます。

CLI での登録は環境変数の値のバイト数が長すぎると登録できない場合があるので注意が必要です。

メリット

CLI で操作できる json ファイルでテンプレート化ができる

デメリット

環境変数の値のバイト数が長すぎると登録できない場合がある 3. AWS SDK

プログラミング言語ごとに用意されている AWS SDK を利用することでも環境変数の登録を行えます。

Java Python Ruby .NET iOS etc... クライアントを Python で実装してみる

登録した環境変数を呼び出すクライアントの実装を Python でやってみます。 Python の AWS SDK である Boto3 を利用します。

import json import boto3 from botocore.exceptions import ClientError class SecretsManager: def __init__(self, aws_region, aws_access_key_id=None, aws_secret_access_key=None): self.aws_region = aws_region self.aws_access_key_id = aws_access_key_id self.aws_secret_access_key = aws_secret_access_key def get_secret_values(self, secret_name): client = boto3.client( 'secretsmanager', aws_access_key_id=self.aws_access_key_id, aws_secret_access_key=self.aws_secret_access_key, region_name=self.aws_region ) try: resp = client.get_secret_value(SecretId=secret_name) secret_values = json.loads(resp['SecretString']) except ClientError: raise except KeyError: raise except json.JSONDecodeError: raise else: return secret_values def get_secret_value(self, secret_key, secret_values): try: secret_value = secret_values[secret_key] except KeyError: raise else: return secret_value

※ AWS_ACCESS_KEY_ID , AWS_SECRET_ACCESS_KEY に関しては適切な IAM Role をアタッチすることで設定不要です。デフォルトのポリシーで SecretsManagerReadWrite があります。

AWS Secrets Manager から環境変数ごとに取得することもできますが、アクセスの回数を抑えるために一度全ての環境変数を取得して、その環境変数から検索するという実装にしています。

サードパーティライブラリaws-sm を公開しました

https://github.com/jumpyoshim/aws-sm

上記の SecretsManager クラスを pip install で使えるようにしました。

インストール $ pip install aws-sm 使い方 from aws_sm import SecretsManager AWS_ACCESS_KEY_ID = *************** AWS_SECRET_ACCESS_KEY = *************** secretsmanager = SecretsManager('ap-northeast-1', AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY) secrets = secretsmanager.get_secret_values('tutorials/MyFristTutorialSecret') USER_NAME = secretsmanager.get_secret_value('USER_NAME', secrets) PASSWORD = secretsmanager.get_secret_value('PASSWORD', secrets)

これは USER_NAME と PASSWORD を tutorials/MyFristTutorialSecret というシークレットから取得するときのシンプルな例です。

AWS Secrets Manager を運用してみた所感

マネージドなサービスに乗っかれるので色々と楽をできます。 しかし、AWS Secrets Manager を利用してもイケてないと感じる点があります。

それは、AWS Secrets Manager に環境変数管理を統一できないことです。

どういうことかというと、アプリケーションの起動や AWS Secrets Manager へのアクセスに必要な環境変数は AWS Secrets Manager で管理できないため、別途管理が必要になるということです。

例えば、AWS Secrets Manager への接続情報に必要な AWS リージョン(IAM でクレデンシャルを管理している場合は IAM も)やアプリケーションフレームワークのシークレットキーがこれに該当します。これらの環境変数はアプリケーションの起動前や AWS Secrets Manager へのアクセス前に値を渡してあげる必要があるため、AWS Secrets Manager で管理することができません。(Django アプリケーションでの話なので、他のフレームワークでは少し異なるかもしれません。)

順番としてはアプリケーションの起動後に AWS Secrets Manager へアクセスして環境変数を取得するという流れになるため当然と言えば当然です。

これらの環境変数はどうしようもないため、 Docker Compose の environment で管理しています。 (Amazon ECS CLI + GitLab でデプロイしていますが、Docker Compose の environment を GitLab の Variables から渡しています。)

AWS Secrets Manager で環境変数の作成や取得が楽になった反面、環境変数の管理が二重化してしまうというデメリットもありました。

おわりに

Twelve Factor App に準拠する Amazon ECS でのアプリケーション開発・運用のつらみ、環境変数地獄を AWS Secrets Manager を利用して対処してみました。

やはりマネージドなサービスに乗っかるのが色々と楽をできます。 しかし、AWS Secrets Manager を利用しても上記のようなつらみがあるのも事実です。

AWS は Python 以外の言語も SDK を公開しており、同じように Secrets Manager を利用することができると思うのでぜひ活用してみてください。

脚注

DjangoCongress JP 2018 「レガシー Django アプリケーションの現代化」 で取り上げられていた問題です。 ↩︎

「Go で s3-edit という CLI アプリケーションを作った」 ↩︎



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有